package com.gticket.cinemauser.handler;

import com.gticket.cinemauser.pojo.Perms;
import com.gticket.cinemauser.pojo.ResponseData;
import com.gticket.cinemauser.pojo.Role;
import com.gticket.cinemauser.pojo.Users;
import com.gticket.cinemauser.service.PermService;
import com.gticket.cinemauser.service.RoleService;
import com.gticket.cinemauser.service.UserService;
import com.gticket.cinemauser.util.RegexUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.Data;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.*;
import java.awt.font.FontRenderContext;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.List;
import java.util.Map;
import java.util.Random;

@Api("g-ticket-cinema-user接口")
@Data
@RestController
public class UserHandler {

    @Autowired
    private UserService userService;
    @Autowired
    private ResponseData responseData;
    @Autowired
    private RoleService roleService;
    @Autowired
    private PermService permService;


    //跳转到登录页面
    //@ApiOperation(value = "跳转到登录页面")
    //@GetMapping("/login")
    //public String login(){
    //    return "login";
    //}
    //登录
    @ApiOperation(value = "登录",notes = "【已完成】")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "remenberMeFlag",value = "是否设置记住我功能",defaultValue = "true"),
            @ApiImplicitParam(name = "user_name",value="账号",defaultValue = "tom"),
            @ApiImplicitParam(name = "user_password",value="密码",defaultValue = "123456"),
            @ApiImplicitParam(name = "code",value="验证码",defaultValue = ""),
            @ApiImplicitParam(name = "databaseName",value = "影院名",defaultValue = "filmforcustomer")
    })
    @PostMapping("/loginCheck")
    public ResponseData login(Users user, HttpServletRequest request, HttpSession session1) {
        String result ;
//        System.out.println("登录+++++++++++++=");
        //System.out.println("登录+++" + user);
        Session session = SecurityUtils.getSubject().getSession();
        //判断验证码
        Object obj = request.getSession().getAttribute("code");
        if (obj == null) {
            result = "请输入验证码！";
            responseData.setCode(200);
            responseData.setData(result);
            responseData.setMessage("未输入验证码");
            return responseData;
        }
        String code = (String) obj;
        if (!code.equalsIgnoreCase(user.getCode())) {
            result = "验证码错误！";//验证码错误
            responseData.setCode(200);
            responseData.setData(result);
            responseData.setMessage("验证码不正确");
            return responseData;
        }

        //System.out.println("这里是登录认证++++++");
        //将传入的user对象存进session中
        session.setAttribute("CheckLoginUser", user);
        //使用shrio进行身份验证
        Subject currentUser = SecurityUtils.getSubject();    //获取"当前用户"
        //判断是否认证过
        if (!currentUser.isAuthenticated()) {
            //没有认证
            System.out.println("没有认证");
            UsernamePasswordToken token =
                    new UsernamePasswordToken(user.getUser_name(), user.getUser_password());
            if (user.isRemenberMeFlag()) {
                token.setRememberMe(true);//设置记住我
            }
            try {
                //进行认证
                currentUser.login(token);
                //如果不包异常，说明认证成功
                //System.out.println("认证成功");
                session.setAttribute("account", user.getUser_name());

            } catch (Exception e) {
                    result = "账号或密码错误！";//帐号或密码错误
//                    System.out.println("帐号密码错误");
                    responseData.setCode(200);
                    responseData.setData(result);
                    responseData.setMessage("账号或密码错误");
                    return responseData;
            }
        }
//      System.out.println("最后认证");
        //认证成功，或已认证跳到首页
        Object object = session.getAttribute("user");
        if (object == null) {
            return null;
        }
        Users user1 = (Users) object;
        session1.setAttribute("username", user1.getUser_name());
        session1.setAttribute("userimage", user1.getUser_image());
        session1.setAttribute("user_id", user1.getUser_id());
        result = "登录成功！";
        //根据用户名查询
        Role role = roleService.selectRoleByUser_name(user);
        //根据角色id查询对应权限
        List<Perms> perms = permService.selectPermsByRole_id(role);
        responseData.setCode(200);
        responseData.setData(result);
        responseData.setMessage("登录成功");
        responseData.setRole(role.getRole_name());
        responseData.setPerms(perms);
        return responseData;
    }

    //注册
    @ApiOperation(value = "注册",notes = "【已完成】")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "user_name",value="账号",defaultValue = "tom"),
            @ApiImplicitParam(name = "user_password",value="密码",defaultValue = "123456"),
            @ApiImplicitParam(name = "code",value="验证码",defaultValue = ""),
            @ApiImplicitParam(name = "databaseName",value = "影院名",defaultValue = "filmforcustomer")
    })
    @PostMapping("/registerCheck")
    public ResponseData register(Users user, HttpServletRequest request) {
        System.out.println(user);
        String result = "注册失败！";
        //System.out.println("注册");
        //未传入用户信息
        if (user == null) {
            responseData.setCode(200);
            responseData.setData(result);
            responseData.setMessage("注册失败");
            return responseData;
        }
        //未传入用户名
        if(user.getUser_name()==null||"".equals(user.getUser_name())){
            result="请输入用户名！";
            responseData.setCode(200);
            responseData.setData(result);
            responseData.setMessage("请输入用户名");
            return responseData;
        }
        //未传入密码
        if(user.getUser_password()==null||"".equals(user.getUser_password())){
            result="请输入密码！";
            responseData.setCode(200);
            responseData.setData(result);
            responseData.setMessage("请输入密码");
            return responseData;
        }
        //验证用户名是否合法
        if(!RegexUtil.isUsername(user.getUser_name())){
            result="请输入2-20位由字母或数字组成的用户名！";
            responseData.setCode(200);
            responseData.setData(result);
            responseData.setMessage("请输入2-20位由字母或数字组成的用户名！");
            return responseData;
        }
        //验证密码是否合法
        if(!RegexUtil.isPassword(user.getUser_password())){
            result="请输入6-20位由字母或数字组成的密码！";
            responseData.setCode(200);
            responseData.setData(result);
            responseData.setMessage("请输入5-20位由字母或数字组成的密码！");
            return responseData;
        }
        //取出传入的用户名
        String account = user.getUser_name();
        //获取验证码真实验证码code，验证码判断
        Object obj = request.getSession().getAttribute("code");
        if (obj == null) {
            result = "请输入验证码！";
            responseData.setCode(200);
            responseData.setData(result);
            responseData.setMessage("请输入验证码");
            return responseData;
        }
        String code = (String) obj;
        if (!code.equalsIgnoreCase(user.getCode())) {
            result = "验证码不正确！";
            responseData.setCode(200);
            responseData.setData(result);
            responseData.setMessage("验证码不正确");
            return responseData;
        }
        //先查询是否帐号存在
        Users findUser = userService.findUserByUser_name(user);
        //System.out.println("帐号" + findUser);
        if (findUser != null) {
            //帐号存在
            result = "该账号已存在！";
            responseData.setCode(200);
            responseData.setData(result);
            responseData.setMessage("该账号已存在");
            return responseData;
        }
        //加密
        user = cryptoPwd(user);
        //设置角色默认为2（普通用户）
        user.setRole_id(2);
        //将注册的用户信息插入用户表并返回user_id
        int user_id = userService.register(user);
        //System.out.println(user_id);
        if (user_id > 0) {
            result = "注册成功！";
            responseData.setCode(200);
            responseData.setData(result);
            responseData.setMessage("注册成功");
            return responseData;
        }
        responseData.setCode(200);
        responseData.setData(result);
        responseData.setMessage("注册失败");
        return responseData;
    }


    //MD5加密
    private Users cryptoPwd(Users user) {
        if (user.getUser_password() != null&&!"".equals(user.getUser_name())) {
            //盐值
            ByteSource byteSource = ByteSource.Util.bytes(user.getUser_name().getBytes());
            //对密码进行加密
            user.setUser_password(new SimpleHash("MD5", user.getUser_password(), byteSource, 1024).toString());
        }
        //将密码加密后的user对象返回
        return user;
    }

    //获取验证码
    @ApiOperation(value = "生成验证码",notes = "【已完成】")
    @GetMapping("/getCode")
    public void getCode(HttpServletRequest request, HttpServletResponse response) {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        //创建验证码对象
        String code = drawImg(outputStream);
        //获取真实验证码值
        System.out.println("真实验证码++" + code);
        request.getSession().setAttribute("code", code);
        //code.createCode();

        try {
            ServletOutputStream out = response.getOutputStream();
            outputStream.writeTo(out);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //画验证码
    private String drawImg(ByteArrayOutputStream outputStream) {
        String code = "";
        for (int i = 0; i < 4; i++) {
            code += randomChar();
        }
        int width = 70;
        int height = 25;
        //创建一个bufferImage对象
        BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
        Font font = new Font("Times New Roman", Font.PLAIN, 20);
        Graphics2D g = bufferedImage.createGraphics();
        g.setFont(font);
        Color color = new Color(66, 2, 82);
        g.setColor(color);
        g.setBackground(new Color(226, 226, 240));
        g.clearRect(0, 0, width, height);
        FontRenderContext context = g.getFontRenderContext();
        Rectangle2D bounds = font.getStringBounds(code, context);
        double x = (width - bounds.getWidth()) / 2;
        double y = (height - bounds.getHeight()) / 2;
        double ascent = bounds.getY();
        double baseY = y - ascent;
        g.drawString(code, (int) x, (int) baseY);
        g.dispose();
        try {
            ImageIO.write(bufferedImage, "jpg", outputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return code;
    }

    //随机生成验证码
    private char randomChar() {
        Random random = new Random();
        String s = "ABCDEFGHJKLMNPQRSTUVWXYZ123456789";
        return s.charAt(random.nextInt(s.length() -1));
    }

    //获取已登录用户名,未登录返回null，已登录返回用户名。。
    @GetMapping("/findLogonUser")
    public ResponseData checkUser(HttpSession session){
        Object object = session.getAttribute("username");
        responseData.setCode(200);
        responseData.setData(object);
        responseData.setMessage("查找已登录用户名");
        return responseData;
    }
}
